//The MIT License
//
//Copyright (c) 2009 nodchip
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
package tv.dyndns.kishibe.client;

import java.util.HashMap;
import java.util.Map;

import tv.dyndns.kishibe.client.packet.PacketProblemData;
import tv.dyndns.kishibe.client.ui.ClickableLabel;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class GridProblemReport extends Grid implements ClickHandler {
	private final boolean regist;
	private final ClickableLabel labelProblemId = new ClickableLabel("問題番号", this);
	private final ClickableLabel labelGenre = new ClickableLabel("ジャンル", this);
	private final ClickableLabel labelType = new ClickableLabel("出題形式", this);
	private final ClickableLabel labelRandomFlag = new ClickableLabel("ﾗﾝﾀﾞﾑ", this);
	private final ClickableLabel labelSentence = new ClickableLabel("問題文", this);
	private final ClickableLabel labelNote = new ClickableLabel("問題ノート", this);
	private final ClickableLabel labelCreator = new ClickableLabel("作成者", this);
	private final ClickableLabel labelCorrect = new ClickableLabel("正解数", this);
	private final ClickableLabel labelWrong = new ClickableLabel("誤答数", this);
	private final ClickableLabel labelCount = new ClickableLabel("回答数", this);
	private final ClickableLabel labelRatio = new ClickableLabel("正答率", this);
	private final ClickableLabel labelVoteGood = new ClickableLabel("良問", this);
	private final ClickableLabel labelVoteBad = new ClickableLabel("悪問", this);
	private final ClickableLabel[] labelColumns = { labelProblemId, labelGenre, labelType, labelRandomFlag, labelSentence, labelNote, labelCreator, labelCorrect, labelWrong, labelCount, labelRatio, labelVoteGood, labelVoteBad };
	private final Map<ClickableLabel, Integer> labelToRegisterId = new HashMap<ClickableLabel, Integer>();
	private final Map<ClickableLabel, Integer> labelToSortById = new HashMap<ClickableLabel, Integer>();
	private final Map<ClickableLabel, Integer> labelToCreationId = new HashMap<ClickableLabel, Integer>();
	private final WidgetProblemReport parent;

	public GridProblemReport(WidgetProblemReport parent, PacketProblemData[] problems, int beginIndex, int endIndex, boolean regist) {
		this.regist = regist;
		this.parent = parent;
		addStyleName("gridFrame");
		addStyleName("gridFontNormal");

		final int numberOfProblems = endIndex - beginIndex;

		// グリッド
		resize(numberOfProblems + 1, labelColumns.length + 1);
		for (int column = 0; column < labelColumns.length; ++column) {
			final ClickableLabel label = labelColumns[column];
			setWidget(0, column, label);
			labelToSortById.put(label, column);
			label.addStyleDependentName("problemReportButton");
		}
		setText(0, labelColumns.length, "登録");

		// セル書式設定
		final CellFormatter cellFormatter = getCellFormatter();
		for (int row = 1; row <= numberOfProblems; ++row) {
			cellFormatter.setAlignment(row, 0, VerticalPanel.ALIGN_CENTER, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 1, VerticalPanel.ALIGN_CENTER, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 2, VerticalPanel.ALIGN_CENTER, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 3, VerticalPanel.ALIGN_CENTER, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 7, VerticalPanel.ALIGN_RIGHT, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 8, VerticalPanel.ALIGN_RIGHT, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 9, VerticalPanel.ALIGN_RIGHT, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 10, VerticalPanel.ALIGN_RIGHT, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 11, VerticalPanel.ALIGN_RIGHT, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 12, VerticalPanel.ALIGN_RIGHT, VerticalPanel.ALIGN_MIDDLE);
			cellFormatter.setAlignment(row, 13, VerticalPanel.ALIGN_CENTER, VerticalPanel.ALIGN_MIDDLE);
		}

		displayProblem(problems, beginIndex, endIndex, regist);
	}

	private void displayProblem(PacketProblemData[] problems, int beginIndex, int endIndex, boolean regist) {
		final CellFormatter cellFormatter = getCellFormatter();
		for (int row = 1, arrayIndex = beginIndex; arrayIndex < endIndex; ++row, ++arrayIndex) {
			final PacketProblemData problem = problems[arrayIndex];

			final int problemId = problem.problemId;
			final ClickableLabel labelCreation = new ClickableLabel(Integer.toString(problemId), this);
			labelToCreationId.put(labelCreation, problemId);
			labelCreation.setWordWrap(false);

			setWidget(row, 0, labelCreation);
			setHTML(row, 1, Constant.NAMES_OF_GENRE[problem.genre]);
			setHTML(row, 2, Constant.NAMES_OF_TYPE_WITH_RANDOM_FLAG[problem.type]);
			setHTML(row, 3, "" + problem.randomFlag);
			setHTML(row, 4, Sanitize.getInstance().html(problem.sentence));
			setHTML(row, 5, Sanitize.getInstance().html(problem.note));
			setHTML(row, 6, Sanitize.getInstance().html(problem.creator != null ? problem.creator : ""));
			setHTML(row, 7, Integer.toString(problem.good));
			setHTML(row, 8, Integer.toString(problem.bad));
			setHTML(row, 9, Integer.toString(problem.good + problem.bad));

			final String ratio;
			if (problem.getCorrectRatio() == -1) {
				ratio = "-";
				Utility.getInstance().setBackgroundColor(getRowFormatter().getElement(row), "#ffffff");
			} else {
				ratio = problem.getCorrectRatio() + "%";
				final double colorRatio = (double) problem.getCorrectRatio() / 100.0;
				Utility.getInstance().setBackgroundColor(getRowFormatter().getElement(row), colorRatio);
			}
			setHTML(row, 10, ratio);

			cellFormatter.addStyleName(row, 4, "gridFontSmall");
			cellFormatter.addStyleName(row, 5, "gridFontSmall");
			cellFormatter.addStyleName(row, 6, "gridFontSmall");

			// 投票ボタン
			final Button buttonVoteGood = new Button(Integer.toString(problem.voteGood));
			final Button buttonVoteBad = new Button(Integer.toString(problem.voteBad));
			buttonVoteGood.setWidth("100%");
			buttonVoteBad.setWidth("100%");

			final ClickHandler clickHandlerVote = new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					final Widget sender = (Widget) event.getSource();
					buttonVoteGood.setEnabled(false);
					buttonVoteBad.setEnabled(false);

					final boolean good = sender == buttonVoteGood;

					final PopupPanelProblemFeedback popupPanelProblemFeedback = new PopupPanelProblemFeedback(problem.problemId, good, (Button) sender);
					final int left = ((Button) sender).getAbsoluteLeft();
					final int top = ((Button) sender).getAbsoluteTop();
					popupPanelProblemFeedback.setPopupPosition(left, top);
					popupPanelProblemFeedback.show();
				}
			};
			buttonVoteGood.addClickHandler(clickHandlerVote);
			buttonVoteBad.addClickHandler(clickHandlerVote);

			setWidget(row, 11, buttonVoteGood);
			setWidget(row, 12, buttonVoteBad);

			// 追加/削除ボタン
			final ClickableLabel labelAdd = new ClickableLabel(regist ? "追加" : "削除", this);
			labelToRegisterId.put(labelAdd, problemId);
			setWidget(row, 13, labelAdd);
		}
	}

	private void processProblemID(int problemId) {
		final int userCode = UserData.getInstance().getUserCode();
		if (regist) {
			Service.Util.getInstance().addProblemIdsToReport(userCode, new int[] { problemId }, Service.NULL_CALLBACK);
		} else {
			Service.Util.getInstance().removeProblemIDFromReport(userCode, problemId, Service.NULL_CALLBACK);
		}
	}

	public void disableRegisterButton() {
		for (ClickableLabel label : labelToRegisterId.keySet()) {
			label.setEnabled(false);
		}
	}

	@Override
	public void onClick(ClickEvent event) {
		final Widget sender = (Widget) event.getSource();
		if (labelToRegisterId.containsKey(sender)) {
			// 問題登録・登録解除
			final int problemID = labelToRegisterId.get(sender);
			processProblemID(problemID);
			final Button button = (Button) sender;
			button.setEnabled(false);
		} else if (labelToCreationId.containsKey(sender)) {
			// 問題作成画面
			final int problemID = labelToCreationId.get(sender);
			Controller.getInstance().showCreationProblem(problemID);
		} else {
			// ソート
			final int sortBy = labelToSortById.get(sender);
			parent.sort(sortBy);
		}
	}
}
